package com.rankeiot.core.sqltoy;

import cn.hutool.core.bean.BeanUtil;
import com.rankeiot.core.Current;
import com.rankeiot.core.data.UserInfo;
import com.rankeiot.core.dict.DataScope;
import com.rankeiot.core.util.StringUtil;

import org.sagacity.sqltoy.model.IgnoreKeyCaseMap;
import org.sagacity.sqltoy.model.QueryExecutor;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class ScopeExecutor {

    private final UserInfo u;
    private String dept;
    private String user;
    private String role;
    private QueryExecutor queryExecutor;
    private IgnoreKeyCaseMap paramsMap;

    public ScopeExecutor(String sql, Serializable params) {
        u = Current.user();
        paramsMap = new IgnoreKeyCaseMap();
        queryExecutor = new QueryExecutor(sql);
        if (params == null) {
            queryExecutor.resultType(Map.class);
        } else if (params instanceof Map) {
            paramsMap = new IgnoreKeyCaseMap((Map) params);
            queryExecutor.resultType(Map.class);
        } else {
            paramsMap = (IgnoreKeyCaseMap) BeanUtil.beanToMap(params, new IgnoreKeyCaseMap<>(), false, true);
            queryExecutor.resultType(org.sagacity.sqltoy.utils.BeanUtil.getEntityClass(params.getClass()));
        }
        queryExecutor.getInnerModel().entity = paramsMap;
    }

    public static ScopeExecutor create(String sqlOrId, Serializable params) {
        return new ScopeExecutor(sqlOrId, params);
    }

    public ScopeExecutor withBranch(String field) {
        this.dept = field;
        return this;
    }

    public ScopeExecutor withSelf(String field) {
        this.user = field;
        return this;
    }

    public ScopeExecutor withRole(String field) {
        this.role = field;
        return this;
    }

    public QueryExecutor executor() {

        String scope = getScope(u,user,dept,role);
        if (scope != null) {
            paramsMap.put("scope", scope);
        }
        return queryExecutor;
    }

    public static String getScope(String user,String dept,String role) {
        return getScope(Current.user(),user,dept,role);
    }
    /**
     * 数据范围判断SQL，有对应字段时，自动拼接上对应查询条件
     * @param u 用户信息
     * @param user 用户字段
     * @param dept 部门字段
     * @param role 角色字段
     * @return scopedSql
     */
    public static String getScope(UserInfo u,String user,String dept,String role) {
        if (u.isSuper()) {
            return null;
        }
        String bsn = u.getBranchSn();
        String username = u.getUsername().replaceAll("'","\\'");

        List<String> sqls = new ArrayList<>();
        for (Map.Entry<String, String> e : u.getScopes().entrySet()) {
            String sc = e.getValue();
            String roleCode = e.getKey();
            //含有全部权限，不需要判断
            if (DataScope.ALL.equals(sc)) {
                return null;
            }
            if (StringUtil.isNotEmpty(dept)) {
                if (DataScope.DEPT.equals(sc)) {
                    sqls.add(dept + "='" + bsn + "'");
                } else if (DataScope.DEPT_AND_CHILD.equals(sc)) {
                    sqls.add(dept + " like '" + bsn + "%'");
                }
            }
            if (DataScope.SELF.equals(sc)) {
                if (StringUtil.isNotEmpty(user)) {
                    sqls.add(user + " = '" + username + "'");
                } else {
                    // 数据权限为仅本人且没有指定username别名不查询任何数据
                    sqls.add("1=0");
                }
            } else if (DataScope.CUSTOM.equals(sc)) {
                if (StringUtil.isNotEmpty(role)) {
                    sqls.add(role + " = '" + roleCode + "'");
                }
            }
        }
        if (sqls.size() > 0) {
            return "(" + String.join(" OR ", sqls) + ")";
        }
        return null;
    }
}
